﻿using System;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.ServiceModel;
using System.ServiceProcess;
using Watchdog.Properties;
using Watchdog.SupervisionService;

namespace Watchdog
{
    partial class Watchdog : ServiceBase
    {
        static String _machineName;
        static String _burglarName = "";
        static String _activityName;
        static Dialer _dialer;
        WireManager _wireManager;
        static SupervisionClient _client;
        static HistoryKeeper _keeper;
        static bool _clientAccesable;


        public static String ActivityName
        {
            get { return _activityName; }
            set
            {
                _activityName = value;
                PropertyChanged();
            }
        }

        private static void PropertyChanged()
        {
            var activity = new PalaceActivity { Name = _activityName, Palace = new Palace { Name = _machineName, Burglar = new Burglar { Name = _burglarName } } };
            if (_clientAccesable)
                try
                {
                    _client.RegisterActivity(activity);
                }
                catch (Exception)
                {
                    RestoreConnection();
                }
            else{
                _keeper.RegisterActivity(activity);
            }
        }


        public ServiceHost ServiceHost = null;

        public Watchdog()
        {
            _machineName = Environment.MachineName.ToString(CultureInfo.InvariantCulture);
            _client = new SupervisionClient();
            _wireManager = new WireManager();
            _keeper = new HistoryKeeper();
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
            InitHost();
            _clientAccesable = InitClient();
            if (!_clientAccesable)
            {
                RestoreConnection();
            }
        }

        private static void RestoreConnection()
        {
            _clientAccesable = false;
            if (_dialer == null)
            {
                _dialer = new Dialer(Settings.Default.DilaingIntervalInSec, InitClient);
                _dialer.OnConnected += OnConnected;
            }
            _dialer.StartCalling();
        }

        private static void OnConnected(object sender, EventArgs eventArgs)
        {
            _clientAccesable = true;
            _keeper.FlushHitory();
        }


        private static bool InitClient()
        {
            try
            {
                _client.RegisterPalace(_machineName);
            }
            catch (Exception e)
            {
                return false;
            }
            return true;
        }

        private void InitWireApp()
        {
            var processCreationThread = new System.Threading.Thread(StartWire);
            processCreationThread.Start();
        }

        private void InitHost()
        {
            if (ServiceHost != null)
            {
                ServiceHost.Close();
            }
            ServiceHost = new ServiceHost(typeof(WireService));
            ServiceHost.Open();
        }

        protected override void OnStop()
        {
            DismissWire();
            UnregisterPalace();
        }

        private void UnregisterPalace()
        {
            if (_clientAccesable)
                _client.RemovePalace(_machineName);
            _client.Close();
        }

        private void DismissWire()
        {
            SetBurglarName("");
            _wireManager.Shutdown();
        }

        protected override void OnSessionChange(SessionChangeDescription changeDescription)
        {
            switch (changeDescription.Reason)
            {
                case SessionChangeReason.SessionLogon:
                    InitWireApp();
                    break;
                case SessionChangeReason.SessionLogoff:
                    DismissWire();
                    break;
            }
        }
        public void StartWire()
        {
            _wireManager.Launch(Settings.Default.WireFilePath);
        }

        public static void SetBurglarName(String pName)
        {
            _burglarName = pName;
            try
            {
                _client.Alert(new InvasionAlert{
                    Palace = new Palace{
                        Name = _machineName,
                        Burglar = new Burglar { Name = _burglarName }
                    }
                });
            }
            catch (Exception)
            {
                RestoreConnection();
            }
        }

    }
}
